package com.mhr.ai.cr.service

import com.intellij.openapi.components.Service
import com.intellij.openapi.diagnostic.thisLogger
import com.intellij.openapi.project.Project
import com.intellij.openapi.vcs.changes.ChangeListManager
import com.intellij.openapi.vcs.VcsException
import com.intellij.openapi.vfs.VirtualFile
import com.mhr.ai.cr.model.ChangeType
import com.mhr.ai.cr.model.FileChange
import com.mhr.ai.cr.model.LocalGitInfo
import git4idea.repo.GitRepositoryManager
import git4idea.commands.Git
import git4idea.commands.GitCommand
import git4idea.commands.GitLineHandler

/**
 * 本地 Git 服务类
 * 负责分析当前项目的 Git 变更
 */
@Service(Service.Level.PROJECT)
class LocalGitService(private val project: Project) {
    
    private val logger = thisLogger()
    
    /**
     * 分析当前项目的 Git 变更
     */
    fun analyzeLocalChanges(): Result<LocalGitInfo> {
        return try {
            logger.info("开始分析本地 Git 变更")
            
            // 检查项目是否是 Git 仓库
            val gitRepositoryManager = GitRepositoryManager.getInstance(project)
            val repositories = gitRepositoryManager.repositories
            
            if (repositories.isEmpty()) {
                return Result.failure(IllegalStateException("当前项目不是 Git 仓库"))
            }
            
            val repository = repositories.first()
            val root = repository.root
            
            // 获取当前分支信息
            val currentBranch = repository.currentBranch?.name ?: "未知分支"
            
            // 获取变更列表
            val changeListManager = ChangeListManager.getInstance(project)
            val allChanges = changeListManager.allChanges.toList()
            
            // 转换为我们的数据模型
            val fileChanges = allChanges.map { change ->
                val beforeRevision = change.beforeRevision
                val afterRevision = change.afterRevision
                
                val changeType = when {
                    beforeRevision == null && afterRevision != null -> ChangeType.ADDED
                    beforeRevision != null && afterRevision == null -> ChangeType.DELETED
                    beforeRevision != null && afterRevision != null -> {
                        if (beforeRevision.file.path != afterRevision.file.path) {
                            ChangeType.RENAMED
                        } else {
                            ChangeType.MODIFIED
                        }
                    }
                    else -> ChangeType.MODIFIED
                }
                
                val oldPath = beforeRevision?.file?.path
                val newPath = afterRevision?.file?.path ?: beforeRevision?.file?.path ?: "unknown"
                
                // 获取文件差异内容
                val (diff, addedLines, removedLines) = try {
                    getDiffContent(repository.root, newPath, changeType)
                } catch (e: Exception) {
                    logger.warn("获取文件差异失败: $newPath", e)
                    Triple("获取差异内容失败: ${e.message}", 0, 0)
                }
                
                FileChange(
                    oldPath = oldPath,
                    newPath = newPath,
                    changeType = changeType,
                    diff = diff,
                    addedLines = addedLines,
                    removedLines = removedLines
                )
            }
            
            // 获取提交信息
            val lastCommitHash = "latest"
            val lastCommitMessage = "最新提交"
            
            val localGitInfo = LocalGitInfo(
                repositoryPath = root.path,
                currentBranch = currentBranch,
                totalChanges = fileChanges.size,
                stagedChanges = allChanges.size,
                unstagedChanges = 0,
                untrackedFiles = 0,
                changes = fileChanges,
                lastCommitHash = lastCommitHash,
                lastCommitMessage = lastCommitMessage
            )
            
            Result.success(localGitInfo)
        } catch (e: Exception) {
            logger.error("分析本地 Git 变更失败", e)
            Result.failure(e)
        }
    }
    
    /**
     * 获取文件的差异内容
     */
    private fun getDiffContent(root: VirtualFile, filePath: String, changeType: ChangeType): Triple<String, Int, Int> {
        return try {
            val git = Git.getInstance()
            val handler = GitLineHandler(project, root, GitCommand.DIFF)
            
            when (changeType) {
                ChangeType.ADDED -> {
                    // 对于新增文件，显示整个文件内容
                    handler.addParameters("--no-index", "/dev/null", filePath)
                }
                ChangeType.DELETED -> {
                    // 对于删除文件，显示删除的内容
                    handler.addParameters("HEAD", "--", filePath)
                }
                ChangeType.MODIFIED, ChangeType.RENAMED -> {
                    // 对于修改文件，显示工作区与暂存区的差异
                    handler.addParameters("HEAD", "--", filePath)
                }
            }
            
            val result = git.runCommand(handler)
            val diffContent = result.outputAsJoinedString
            
            // 统计添加和删除的行数
            val lines = diffContent.lines()
            var addedLines = 0
            var removedLines = 0
            
            lines.forEach { line ->
                when {
                    line.startsWith("+") && !line.startsWith("+++") -> addedLines++
                    line.startsWith("-") && !line.startsWith("---") -> removedLines++
                }
            }
            
            Triple(diffContent, addedLines, removedLines)
        } catch (e: VcsException) {
            logger.warn("执行 git diff 命令失败", e)
            Triple("Git diff 执行失败: ${e.message}", 0, 0)
        } catch (e: Exception) {
            logger.warn("获取差异内容时发生未知错误", e)
            Triple("获取差异内容失败: ${e.message}", 0, 0)
        }
    }
}